package com.jwtproject.bootserver.security.oauth;


import com.jwtproject.bootserver.security.config.CustomAccessDecisionManager;
import com.jwtproject.bootserver.security.config.CustomFilterInvocationSecurityMetadataSource;
import com.jwtproject.bootserver.security.handler.SecurityAccessDeniedHandler;
import com.jwtproject.bootserver.security.handler.SecurityAuthenticationEntryPointHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.ObjectPostProcessor;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;

@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {

    @Resource
    private SecurityAccessDeniedHandler securityAccessDeniedHandler;

    @Resource
    private CustomFilterInvocationSecurityMetadataSource customFilterInvocationSecurityMetadataSource;

    @Resource
    private CustomAccessDecisionManager customAccessDecisionManager;

    @Resource
    private SecurityAuthenticationEntryPointHandler securityAuthenticationEntryPointHandler;


    @Override
    public void configure(ResourceServerSecurityConfigurer resources) {
        resources.resourceId("rid") // 配置资源id，这里的资源id和授权服务器中的资源id一致
                .stateless(true); // 设置这些资源仅基于令牌认证
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http
                .csrf().disable()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED) // 另外，如果不设置，那么在通过浏览器访问被保护的任何资源时，每次是不同的SessionID，并且将每次请求的历史都记录在OAuth2Authentication的details的中
                .and()
                .authorizeRequests().anyRequest().authenticated()  // httpSecurity 放过健康检查，其他都需要验证  设置了.anyRequest().authenticated()才回进入自定义的权限判断
//                .and()
//                .requestMatchers().antMatchers("/auth/**") // .requestMatchers().antMatchers(...) OAuth2设置对资源的保护如果是用 /**的话 会把上面的也拦截掉
                .and()
                .authorizeRequests()
                .withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() {       // 重写做权限判断
                    @Override
                    public <O extends FilterSecurityInterceptor> O postProcess(O object) {
                        object.setSecurityMetadataSource(customFilterInvocationSecurityMetadataSource);
                        object.setAccessDecisionManager(customAccessDecisionManager);
                        return object;
                    }
                })

                .and()
                .httpBasic();

        http.exceptionHandling().authenticationEntryPoint(securityAuthenticationEntryPointHandler)
                .accessDeniedHandler(securityAccessDeniedHandler);
    }
}
